`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: HITSZ
// Engineer: 
// 
// Create Date: 2023/11/3
// Design Name: 
// Module Name: decode
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////

module rx_decode #
(
    parameter integer SWITCH_WIDTH = 24,
    parameter integer BUTTON_WIDTH = 5,
    parameter HAS_KEYBOARD = 1
    /// Because it is normal for 4x4 keyboard, we will make it inmutable.
    // parameter integer KEYBOARD_ROW_WIDTH = 4,
    // parameter integer KEYBOARD_COL_WIDTH = 4
)
(
    input wire clk,
    input wire rstn,
    input wire [7:0] code,
    input wire decode_en,
    input wire [3:0] keyboard_col,
    input wire group_done,
    
    output reg [SWITCH_WIDTH - 1:0] switch = 0,
    output reg [BUTTON_WIDTH - 1:0] button = 0,
    output wire [3:0] keyboard_row,
    output reg sample_en = 0
);

    // A new encode format:
    // code -> 8 bit [x][ ][ ][ ][ ][ ][ ][ ]
    // name     num  format
    // switch   32   [x][0][0][ ][ ][ ][ ][ ]
    // button   16   [x][0][1][0][ ][ ][ ][ ]
    // keyboard 16   [x][0][1][1][ ][ ][ ][ ]
    // reserve  16   [x][1][0][0][ ][ ][ ][ ]
    // reserve  16   [x][1][0][1][ ][ ][ ][ ]
    // reserve  31   [x][1][1][ ][ ][ ][ ][ ]
    // smpl_on  1    [1][1][1][1][1][1][1][1]
    // smpl_off 1    [0][1][1][1][1][1][1][1]

    wire code_on;
    assign code_on = code[7];

    reg wait_for_group_done;

    reg [4:0] aux;
    reg keyboard_on;

    always @ (posedge clk) begin
        if (~rstn) begin
            switch <= 0;
            button <= 0;
            sample_en <= 0;
            aux <= 5'd16;
            keyboard_on <= 0;
        end
        else if (decode_en) begin
            // switch 
            if (code[6:5] == 2'b00 && code[4:0] < SWITCH_WIDTH) 
                switch[code[4:0]] <= code_on;
            
            // button
            else if (code[6:4] == 3'b010 && code[3:0] < BUTTON_WIDTH)  
                button[code[3:0]] <= code_on;

            // keyboard
            else if (code[6:4] == 3'b011 && HAS_KEYBOARD) begin
                aux <= code[3:0];
                keyboard_on <= code_on;
            end
    
            // sample_on
            // sample_en must be 1 during the whole process of transmitting every 5 bytes as a group
            // when turn off sample_en, it must wait for a complete transmition process of a group
            else if (code[6:0] == 7'h7f) begin
                if (code_on) 
                    sample_en <= 1'b1;
                
                else if (~code_on && group_done) 
                    sample_en <= 1'b0;
                
                else if (~code_on && ~group_done) 
                    wait_for_group_done <= 1'b1;
            end
        end 
        else if (wait_for_group_done && group_done) begin
            sample_en <= 1'b0;
            wait_for_group_done <= 1'b0;
        end
    end

    // assign keyboard_row
    // keyboard actually can press many buttons simultaneously, 
    // but here we only implement mutex 16 buttons.
    assign keyboard_row = {
        (aux >= 0 && aux < 4) ?
        ~keyboard_on | keyboard_col[3 - (aux & 5'h3)] : 1'b1,
        (aux >= 4 && aux < 8) ?
        ~keyboard_on | keyboard_col[3 - (aux & 5'h3)] : 1'b1,
        (aux >= 8 && aux < 12) ?
        ~keyboard_on | keyboard_col[3 - (aux & 5'h3)] : 1'b1,
        (aux >= 12 && aux < 16) ?
        ~keyboard_on | keyboard_col[3 - (aux & 5'h3)] : 1'b1
    };

endmodule


